home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 1250 / BCPP18.ZIP / BCPP / CODE / BCPP.CPP < prev   
Encoding:
C/C++ Source or Header  |  1995-12-23  |  76.9 KB  |  2,136 lines

  1. // C(++) Beautifer V1.61 Unix/MS-DOS update !
  2. // -----------------------------------------
  3. //
  4. // Program was written by Steven De Toni 1994 (CBC, ACBC).
  5. // This program attempts to alter C, C++ code so that it fits to a
  6. // format that the user wants.
  7. // This program is the result of a project that needed to be written
  8. // for a module that I was doing at the Waikato Polytech.
  9. // Course     : Advanced Certificate In Business Computing (ACBC)
  10. // Module     : PR-300.
  11. // Assignment : Project 1, approx 60 hours.
  12. //
  13. // The program reads a configuration file that has the user's settings.
  14. // Input, and output files are via the command line.
  15. //
  16. // If compiling under DOS, use Large memory model, any other
  17. // type of system (i.e Unix, Amiga), use default.
  18. // I have tryed to use all standard Unix functions for I/O to keep
  19. // the Unix programmers happy.
  20. //
  21. // NOTE:
  22. // This code has never been tested under any other system other than MS-DOS.
  23. // All program code is public domain, you can use any part of this
  24. // code on the condition that my name be placed somewhere within documentation,
  25. // or program. However, all rights are reserved as to the program logic, that
  26. // is to say, you can change it, give it to people, but my name must still
  27. // exist within the credits of the old, or newly altered program (Programmers Ethics).
  28. //
  29. // ###################################################################################
  30. //
  31. // Program Update : 14/11/94 V1.5
  32. //
  33. // Removed a couple more bugs, optimised code (not that you notice it),
  34. // added the following features:
  35. //     - Able to decode lines fully (uses recursion)
  36. //     - Able to handle unlimited depth handling for single indent code.
  37. //     - Added command line parameter processing (able use i/o redirection)
  38. //     - Added variable internal buffer length (used for repositioning of braces)
  39. //
  40. // ###################################################################################
  41. //
  42. // Program Update : 21/11/94 V1.55
  43. //
  44. // Compiling done using GNU G++, brilliant compiler ...
  45. // Dos debugger (debug32) sucked totally compared to Borlands programming
  46. // environment, ended up using a series of printf statements in debugging !
  47. //
  48. // Program functions perfectly under Sun SPARC station running SunOs V??,
  49. // compiled using GNU G++ V2.6.?. Version 1.05 of the GNU running under
  50. // DOS functions brilliantly, except for input redirection fails. I think this
  51. // could be due to fseek() failing to move back, and forward within the input
  52. // stream. Under Unix, this isn't a problem as pipes/redirections are handled
  53. // properly !
  54. //
  55. // Removed/fixed segmentation violations picked up by G++ within code!
  56. //
  57. //     - Removed non-existing enum constant out of fseek() (I didn't know)
  58. //     - Wrote my own string upper case routine as standard string.h
  59. //       didn't have it (again I didn't know).
  60. //     - Fix a couple of string constants, and few other odds and ends.
  61. //
  62. // ###################################################################################
  63. //
  64. // Program Update : 24/11/94 V1.6 <Final>
  65. //
  66. // Final version update of this program.
  67. //
  68. //      - Added a time feature to show long processing of the input
  69. //        data stream took ... just because I could.
  70. //
  71. //      - Fixed tab space size so that code lines are calculated at correct
  72. //        lengths according to indent spacing.
  73. //
  74. //      - Implemented a backup feature for the input file, and changed the
  75. //        selection of input/output file to the Unix standard.
  76. //
  77. //      - fix the following decode problems
  78. //        if (strcmp (pAString, "A String") == 0) // test for "A String"
  79. //                                                ^
  80. //                                                |
  81. //  Not recoginised as a comment becuase of the quotes chars!
  82. //
  83. //      - struct a { int b, c, d; } as;
  84. //        The above now gets decoded properly.
  85. //
  86. //      - able to indent multiple depthed switch like structures properly.
  87. //
  88. // ###################################################################################
  89. //
  90. // Program Update : 9/1/95 V1.61 <User Patch>
  91. //
  92. //      - Able to set indentation of comments with no code the same as normal code,
  93. //        this results in the comments lining up with the code.
  94. //
  95. //      This option was brought to you by a Candian user Justin Slootsky.
  96. //
  97. // ###################################################################################
  98. //
  99. // Program Update : 19/2/95 V1.62 <Error Update>
  100. //
  101. // Fixed error that was caused when C style comment was placed in the wrong
  102. // placed which caused program output to be wrong
  103. //
  104. // if (someCode) /* C Style Comment
  105. //
  106. // <may end up like the follow ing code !>
  107. //
  108. //         /* C Style Comment
  109. // if (someCode)
  110. //
  111. // Fixed output error is multi-if statements were nested together, and have
  112. // have code within braces after them.
  113. //
  114. // if (someCode) { someCode; }
  115. // if (someCode) { someCode; }
  116. //
  117. // <ended up line>
  118. //
  119. // if (someCode) { someCode; }
  120. //    if (someCode) { someCode; }
  121. //
  122. // ###################################################################################
  123. //
  124. // Program Update : 10/3/95 V1.629 <PreProcessor Update>
  125. //
  126. // Fixed problems with preprocessor statements. All preprocessor statements
  127. // are place at column 1.
  128. //
  129. // ###################################################################################
  130. //
  131. // Program Update : 4/5/95 V1.7 <C comment fix>
  132. //
  133. // Fixed removing of spaces in c style multiline comments
  134. // Remove bug with c style comment that has code before it (uses recursion as a fix)
  135. // Added location of program to use bcpp.cfg configuration without specifing
  136. // it with options (i.e. uses PATH variable to locate).
  137. // ###################################################################################
  138. //
  139. // Program Update : 27/11/95 V1.75 <Single if, while, do, statements fixed>
  140. //
  141. // Fixed the indentin of single statements so they dont become corrupt, and
  142. // line up with previous code.
  143. // Also some simple logic errors where found by users and fixed.
  144. //
  145. // ###################################################################################
  146. //
  147. // Program Update : 06/12/95 V1.8 (Bug was created when ported to Unix and
  148. // trying to prevent segmentation errors, this has been fixed. The problem
  149. // caused incorrect indenting of code if a 'if' statement was within a case
  150. // structure.
  151.  
  152.  
  153. #include <stdlib.h>            // getenv()
  154. #include <time.h>              // time()
  155. #include <string.h>            // strlen(), strstr(), strcpy(), strcmp()
  156. #include <stdio.h>             // NULL constant, printf(), getc(),stdin, stdout, stderr
  157. #include "anyobj.h"            // Use ANYOBJECT base class
  158. #include "baseq.h"             // QueueList class to store Output structures
  159. #include "stacklis.h"          // StackList class to store indentStruct
  160. #include "cmdline.h"           // ProcessCommandLine()
  161. #include "config.h"            // SetConfig()
  162.  
  163. // ----------------------------------------------------------------------------
  164. const int IndentWordLen  = 9;   // number of indent words in pIndentWords
  165. const int MultiIndent    = 4;   // pos in pIndentWords where multi-line indent starts
  166.  
  167. const char pIndentWords [IndentWordLen][10] =
  168. {
  169.     "if", "while", "for", "else",                       // single line indentation
  170.     "case", "default", "public", "protected", "private" // multi-line indentation
  171. };
  172.  
  173. enum  DataTypes { CCom = 1,   CppCom = 2, Code  = 3,
  174.                   OBrace = 4, CBrace = 5, PreP = 6, ELine = 7
  175.                 };
  176. // ----------------------------------------------------------------------------
  177.  
  178. // ----------------------------------------------------------------------------
  179. // This structure is used to store line data that is de-constructed from the
  180. // user's input file.
  181. class InputStruct : public ANYOBJECT
  182. {
  183.     public:
  184.  
  185.     DataTypes dataType;       // i.e "/*" or "*/"                  (1)
  186.                               //     "//"                          (2)
  187.                               //     Code (a = 5; , if (a == b) .. (3)
  188.                               //     "{"                           (4)
  189.                               //     "}"                           (5)
  190.                               //     #define                       (6)
  191.                               //     SPACES (nothing, blank line)  (7)
  192.  
  193.  
  194.     Boolean attrib;
  195.                               //       -1 : True,  comment with code (for comment dataType)
  196.                               //        0 : False, comment with no Code
  197.  
  198.     char* pData;              // pointer to queue data !
  199. };
  200.  
  201.  
  202. // ----------------------------------------------------------------------------
  203. // The output structure is used to hold an entire output line. The structure is
  204. // expanded with it's real tabs/spaces within the output function of the program.
  205. class OutputStruct : public ANYOBJECT
  206. {
  207.     public:
  208.            int   indentSpace;  // num of spaces
  209.            char* pCode;
  210.            char* pBrace;       // "}" or "{"
  211.            int   filler;       // num of spaces
  212.            char* pComment;
  213.  
  214.            // Constructor
  215.            // Automate initalisation
  216.            inline  OutputStruct  (void)
  217.            {
  218.                 pCode = pBrace = pComment = NULL;
  219.                 indentSpace    = filler   = 0;
  220.            }
  221.  
  222.            // Destructor
  223.            // Automate destruction
  224.            inline ~OutputStruct (void)
  225.            {
  226.                 delete pCode;
  227.                 delete pBrace;
  228.                 delete pComment;
  229.            }
  230. };
  231.  
  232.  
  233. // This structure is used to hold indent data on non-brace code.
  234. // This includes case statements, single line if's, while's, for statements...
  235. class IndentStruct : public ANYOBJECT
  236. {
  237.     public:
  238.            // attribute values ...
  239.            // value 1 = indent code one position, until a ';' is found !
  240.            //       2 = end on close brace, and at a position
  241.            unsigned char attrib;
  242.            int           pos;
  243.  
  244.            // Indent double the amount for multiline single if, while ...
  245.            // statements.
  246.            int           singleIndentLen;
  247.            Boolean       firstPass; // user to determine if more than a single line
  248.                                     // if, while... statement.
  249.  
  250.     // constructor
  251.     inline IndentStruct (void)
  252.     {
  253.         attrib = pos = 0;
  254.  
  255.         singleIndentLen = 0; // number of spaces to indent !
  256.         firstPass       = False;
  257.     }
  258. };
  259.  
  260. // ----------------------------------------------------------------------------
  261. // Function expands tabs to spaces; the number of spaces to expand to is
  262. // dependant upon the tabSpaceSize parameter within user settings, and
  263. // tab column positions.
  264. //
  265. // Parameters:
  266. //      pString     : Pointer to the string to process !
  267. //      tabLen      : How much a tab is worth in spaces.
  268. //
  269. // Return Values:
  270. //      char*       : Pointer to newly constructed string, return NULL
  271. //                    if memory allocation problems.
  272. //
  273. char* ExpandTabs (char* pString, int tabLen)
  274. {
  275.    int   count = 0;
  276.    char* pSTab = pString;
  277.    
  278.    while (*pSTab != NULLC)
  279.    {
  280.        count++;
  281.        
  282.        if (*pSTab == TAB)                       // calculate tab positions !
  283.        {
  284.             int tabAmount = 0;
  285.             
  286.             // tab is first character !!!!    
  287.             if (count == 1)
  288.                 tabAmount = tabLen;
  289.             else
  290.                 tabAmount = (((count / tabLen)+1) * tabLen) - count;
  291.             
  292.             if (tabAmount > 0)
  293.             {
  294.                 // create newString, remove tab !
  295.                 char* pNewString = new char[strlen (pString) + tabAmount + 1];
  296.                 char* pAddSpc    = NULL;
  297.                 
  298.                 if (pNewString == NULL)
  299.                 {
  300.                     delete pString;
  301.                     return NULL;
  302.                 }
  303.                 
  304.                 *pSTab = NULLC;                 // remove tab from string !
  305.                 // copy first part
  306.                 strcpy (pNewString, pString);
  307.                 
  308.                 // add spaces 
  309.                 pAddSpc = pNewString + strlen (pNewString);
  310.                 while (tabAmount > 0)
  311.                 {
  312.                     *pAddSpc = ' ';
  313.                     pAddSpc++;
  314.                     tabAmount--;
  315.                 }    
  316.                 
  317.                 // add original trailing spaces
  318.                 strcpy (pAddSpc, pSTab+1);
  319.                 delete pString;                 // remove old string from memory
  320.                 pString = pNewString;
  321.                 pSTab   = pString;
  322.                 count   = 0;
  323.                 continue;                       // restart the operation!
  324.             }
  325.             else
  326.                 *pSTab = ' ';
  327.             
  328.        }
  329.        pSTab++; 
  330.            
  331.    }  
  332.    
  333.    return pString; 
  334. }
  335.  
  336.  
  337. // ----------------------------------------------------------------------------
  338. // Function returns a True/False value according if a word/character is
  339. // contained within quotes within a string.
  340. // examples: hello "world"        : world lies within quotes (returns True)
  341. //           hello 'world'        : same as above
  342. //           "hello" world        : world no long lies within quotes (returns false)
  343. //
  344. // Parameters:
  345. // pLeftLoc      : Pointer in the string of the left most starting position to
  346. //                 start searching.
  347. // pRightLoc     : Pointer in the string of the right most starting position to
  348. //                 start searching.
  349. // pStartOfString: Pointer to the actual start location of the string that is
  350. //                 going to be searched.
  351. //
  352. // Return Values :
  353. // Boolean       : Returns True if sub-string is within quotes, else returns
  354. //                 False.
  355. //
  356. Boolean CheckCharsWithinQuotes (char* pLeftLoc, char* pRightLoc, char* pStartOfString)
  357. {
  358.     char* pDQuote   = "\"";
  359.     char* pSQuote   = "'";
  360.     char* pTQuote   = NULL;
  361.     
  362.     while (  (pLeftLoc >= pStartOfString) && ((*pLeftLoc != '"') && (*pLeftLoc != '\'')) )
  363.               pLeftLoc--;
  364.  
  365.     while ( (*pRightLoc != NULLC) && ((*pRightLoc != '"') && (*pRightLoc != '\'')) )
  366.               pRightLoc++;
  367.  
  368.     if  ((*pLeftLoc == '"') && (*pRightLoc == '"'))
  369.         pTQuote = pDQuote;
  370.         else if  ((*pLeftLoc == '\'') && (*pRightLoc == '\''))
  371.              pTQuote = pSQuote;
  372.  
  373.     if  (pTQuote != NULL)
  374.     {
  375.         // scan from left to right testing for multiple "quotes !"
  376.         char* pTLeft  = pStartOfString;
  377.         char* pTRight = pStartOfString;
  378.  
  379.         for (;;)
  380.         {
  381.             pTLeft = strstr (pTLeft, pTQuote);
  382.             if (pTLeft == NULL)
  383.                return False;
  384.             else if (*(pTLeft-1) == '\\')   // a constant !
  385.                  {
  386.                     pTLeft++;
  387.                     continue;               // continue next search !
  388.                  }
  389.  
  390.             char* pBackup = pTLeft;
  391.             do
  392.             {
  393.                 pTRight = strstr (pTLeft+1, pTQuote);
  394.                 if (pTRight == NULL)
  395.                    return False;
  396.                 else if (*(pTRight-1) == '\\')
  397.                         pTLeft = pTRight;
  398.  
  399.             } while (*(pTRight-1) == '\\');
  400.  
  401.             pTLeft = pBackup;
  402.  
  403.             if ((pLeftLoc >= pTLeft) && (pRightLoc <= pTRight))
  404.                return True;
  405.  
  406.             pTLeft = pTRight+1;
  407.         }
  408.     }
  409.  
  410.     return False;
  411. }
  412.  
  413.  
  414. // ----------------------------------------------------------------------------
  415. // Function is used to test if characters found on a line arn't just
  416. // C++ comments in disguise. This is used to test C comments.
  417. // example // /* C comment*/              : returns True
  418. //         /* C comment*/ // C++ comment  : returns False
  419. //
  420. // Parameters:
  421. // pLeftLoc       : Pointer to the start of the sub-string to start searching
  422. //                  left for a C++ comment
  423. // pStartOfString : Pointer to the actual start location of the whole string
  424. //                  that is going to be searched.
  425. //
  426. // Return Values:
  427. // Boolean      : Returns True if sub-string is within a C++ comment,
  428. //                else returns False
  429. //
  430. Boolean CheckCharsNotCppComments (char* pLeftLoc, char* pStartOfString)
  431. {
  432.     char* pCppCommentLoc = strstr (pStartOfString, "//");
  433.  
  434.     if ((pCppCommentLoc != NULL) && (pCppCommentLoc < pLeftLoc))
  435.         return True;
  436.     else
  437.         return False;
  438. }
  439.  
  440.  
  441. // ----------------------------------------------------------------------------
  442. // Function removes leading, trailing, both leading/trailing characters
  443. // that are less than or equal to a space character (includes spaces, tabs etc)
  444. //
  445. // Parameters:
  446. // pLineData : Pointer to the start location of the string that's going to be processed
  447. // mode      : Bit values that define the removal of characters from the string...
  448. //             1 = remove spaces from left
  449. //             2 = remove spaces from right
  450. //             3 = remove spaces from left, and right
  451. //
  452. // Return Values:
  453. // char*     : Returns a pointer to the newly reformated string.
  454. //
  455. char* StripSpacingLeftRight (char* pLineData, int mode = 3)
  456. {
  457.              int   counter   = strlen (pLineData);
  458.     unsigned char* pLeftPos  = (unsigned char*) pLineData;
  459.     unsigned char* pRightPos = (unsigned char*) pLineData + counter;
  460.  
  461.  
  462.     // find left start of code !
  463.     // over chars that are greater than 32 !
  464.  
  465.     if ((mode & 1) == 1)
  466.     {
  467.         while ((*pLeftPos <= 32) && (counter > 0))
  468.         {
  469.             pLeftPos++;
  470.             counter--;
  471.         }
  472.     }
  473.  
  474.     // find right start of code !
  475.     // over chars that are greater than 32 !
  476.     if ((mode & 2) == 2)
  477.     {
  478.         while ((*pRightPos <= 32)  && (pRightPos > pLeftPos))
  479.               pRightPos--;
  480.     }
  481.  
  482.     // copy that part of the code to the start of the string
  483.     if (counter == 0)
  484.        pRightPos[0] = NULLC;  // create null string
  485.     else
  486.        pRightPos[1] = NULLC;  // create a shortened string
  487.  
  488.     pLineData = strcpy (pLineData, (char*) pLeftPos);
  489.  
  490.     return pLineData;
  491. }
  492.  
  493.  
  494. // ----------------------------------------------------------------------------
  495. // Function takes a unsigned char and converts it to a C type string that
  496. // contains the char's value, but in octal (i.e "\000" = null char).
  497. //
  498. // Parameters:
  499. // value     : The value that wishes to be converted
  500. //
  501. // Return Values:
  502. // char*     : Returns a pointer to the string that was converted.
  503. // Memory is allocated via the new command, and once string has been used,
  504. // memory should be returned to the system.
  505. //
  506. char* ConvertCharToOctal (unsigned char value)
  507. {
  508.     const char octalVals[] = "01234567";
  509.  
  510.     char* pOctalValue = new char[5]; // \000 digits plus null terminator
  511.  
  512.     if (pOctalValue != NULL)
  513.     {
  514.  
  515.         for (int pos = 3; pos >= 1; pos--)
  516.         {
  517.             pOctalValue[pos] = octalVals[(value & 7)];
  518.             value >>= 3; // left shift to next three bits
  519.         }
  520.         pOctalValue[0] = '\\';
  521.         pOctalValue[4] = '\0';
  522.  
  523.     }
  524.  
  525.     return pOctalValue;
  526. }
  527.  
  528.  
  529. // ----------------------------------------------------------------------------
  530. // This function will strip any non-printable characters from a string,
  531. // any characters between quotes are converted to octal character notation,
  532. // if quoteChar parameter set.
  533. //
  534. // Parameters:
  535. // pLineData  : Pointer to the string to process
  536. // mode       : The type of characters to strip, and move over ...
  537. //          1 : Remove non-printing chars (i.e control chars, non-ASCII chars).
  538. //          3 : Same as above cept leave graphic chars alone.
  539. // quoteChars : Boolean char used to change non-ascii chars that lie within
  540. //            : quotes to character/octal notation if set to True.
  541. //
  542. // Return Values:
  543. // char*      : Returns a pointer to the newly altered string (if any chars removed).
  544. //
  545. char* StripNonPrintables (char* pLineData, int mode, Boolean quoteChars)
  546. {
  547.     unsigned char* pCheckByte = (unsigned char*) pLineData;
  548.  
  549.     while (*pCheckByte != NULLC)
  550.     {
  551.     Boolean removeChar = False;
  552.  
  553.         // type cast unsigned chars to ints to stop compiler wingeing.
  554.         switch (mode)
  555.         {
  556.             case (1):
  557.             {
  558.                 // remove chars below a space, but not if char is a TAB.
  559.                 // Remove chars if greater than 127 (non ascii ... IBM)
  560.                 if ( ((( (int) *pCheckByte > 0)   && ((int) *pCheckByte <= 31) ) && ((int) *pCheckByte != 9)) ||
  561.                      (( (int) *pCheckByte >= 127) && ( (int) *pCheckByte <= 255)) )
  562.                    removeChar = True;
  563.                 break;
  564.             }
  565.             case (3):
  566.             {
  567.                 if ( ((( (int) *pCheckByte > 0)   && ((int) *pCheckByte <= 31) ) && ((int) *pCheckByte != 9)) ||
  568.                      (( (int) *pCheckByte >= 127) && ( (int) *pCheckByte <= 175)) )
  569.                 {
  570.                    // check for non graph chars
  571.                    if (( (int) *pCheckByte >= 224) && ( (int) *pCheckByte <= 255))
  572.                        removeChar = False; // graphic char
  573.                    else
  574.                        removeChar = True;  // a non-graphic char !
  575.                 }
  576.                 break;
  577.             }
  578.         } // switch
  579.  
  580.         if (removeChar != False) // remove char from string
  581.         {
  582.             Boolean shuffleChars = True;
  583.  
  584.             // test to see if char lies within quotes, if true then covert it to
  585.             // octal !
  586.             // Do test if not CPP comment !!!
  587.             if ((CheckCharsWithinQuotes   ((char*)pCheckByte, (char*)pCheckByte, pLineData) != False) &&
  588.                 (quoteChars == True))
  589.             {
  590.                 char* pStartQuote = strstr (pLineData, "\""); // try find first type of quote in string
  591.  
  592.                 if (pStartQuote == NULL)   // find other type of quote if other doesn't exist
  593.                    pStartQuote = strstr (pLineData, "'");
  594.  
  595.                 // char isn't within a cpp comment !
  596.                 if (CheckCharsNotCppComments (pStartQuote, pLineData) == False)
  597.                 {
  598.  
  599.                     char* pOctalVal  = ConvertCharToOctal (*pCheckByte);
  600.                     char* pTempStore = new char[strlen(pLineData)+strlen(pOctalVal)+1]; // include length of octal, plus null terminator
  601.  
  602.                     // memory allocation failed
  603.                     if ((pTempStore == NULL) || (pOctalVal == NULL))
  604.                     {
  605.                         delete pOctalVal;
  606.                         delete pTempStore;
  607.                         delete pLineData;
  608.                         return NULL;
  609.                     }
  610.  
  611.                     *pCheckByte     = NULLC; // terminate offending char
  612.                     // concatinate orignal string, octal string, and remaining original string!
  613.                     strcpy (pTempStore, pLineData);   // copy first part of string
  614.                     strcpy (pTempStore + strlen(pTempStore), pOctalVal);
  615.                     strcpy (pTempStore + strlen(pTempStore), (char*)pCheckByte+1);
  616.  
  617.                     delete pLineData;
  618.                     delete pOctalVal;
  619.                     pLineData       = pTempStore;
  620.                     pCheckByte      = (unsigned char*) pLineData; // rescan line !
  621.  
  622.                     shuffleChars    = False;                      // bypass removing char !
  623.                 } // if chars not within a cpp comment !
  624.             }
  625.  
  626.             // remove char from string, so long it's not within a quote !
  627.             if ((shuffleChars != False) &&
  628.                 (CheckCharsWithinQuotes   ((char*)pCheckByte, (char*)pCheckByte, pLineData) == False))
  629.             {
  630.  
  631.                 // shuffle next char over offending non-printg char !
  632.                 unsigned char* pShuff = pCheckByte;
  633.  
  634.                 while (*pShuff != NULLC)
  635.                 {
  636.                       pShuff[0] = pShuff[1];
  637.                       pShuff++;
  638.                 }
  639.                 pCheckByte--;   //recheck copied char over original!
  640.             }
  641.  
  642.         } // remove/alter char from/in string !
  643.  
  644.         pCheckByte++;
  645.     }// while
  646.  
  647.     return pLineData;
  648. }
  649.  
  650.  
  651. // ----------------------------------------------------------------------------
  652. // Function returns a Boolean value that shows where code is contained within
  653. // a string. Any chars within a string above space are consided code.
  654. //
  655. // Parameters:
  656. // pLineData : Pointer to a string to process.
  657. //
  658. // Return Values:
  659. // Boolean   : False = line has no code
  660. //             True  = line has some sort of code
  661. //
  662. Boolean TestLineHasCode (char* pLineData)
  663. {
  664.     // save on segmentation error !   
  665.     if (pLineData == NULL)
  666.        return False;
  667.           
  668.     unsigned char* pTest = (unsigned char*) pLineData;
  669.     int      len         = strlen (pLineData);
  670.  
  671.     while ((*pTest < 33) && (*pTest > 0))
  672.         pTest++;
  673.  
  674.     if ((*pTest != 0) && (len > 0)) // if not null ending char, and char has length
  675.         return True;
  676.     else
  677.         return False;
  678. }
  679.  
  680.  
  681. // ----------------------------------------------------------------------------
  682. // This function is used within function DecodeLine(), it creates a new
  683. // InputStructure and stores whats is contained in pLineData string in
  684. // the newly created structure.
  685. //
  686. // Parameters:
  687. // pLineData  : Pointer to the string to store within the InputStructure.
  688. // dataType   : Type of data that is to be stored within the InputStructure
  689. //              see DataTypes enum.
  690. //
  691. // Return Values:
  692. // InputStruct* : Returns a pointer to the newly constructed InputStructure,
  693. //                returns a NULL value is unable to allocate memory.
  694. //
  695. InputStruct* ExtractCode (char*    pLineData, DataTypes dataType = Code,
  696.                           Boolean  removeSpace = True)
  697. {
  698.     char* pNewCode =  new char[strlen (pLineData)+1];
  699.  
  700.     // ############## test memory #############
  701.     if (pNewCode == NULL)
  702.         return NULL;
  703.  
  704.     pNewCode = strcpy (pNewCode, pLineData);
  705.     
  706.     // create new queue structure !
  707.     InputStruct* pItem = new InputStruct();
  708.     if (pItem != NULL)
  709.     {
  710.             // strip spacing in new string before storing
  711.             if (removeSpace != False)
  712.                 pItem -> pData    = StripSpacingLeftRight (pNewCode);
  713.             else
  714.                 pItem -> pData = pNewCode;
  715.             pItem -> dataType = dataType;
  716.             pItem -> attrib   = False;     // no applicable
  717.     }
  718.     else
  719.         delete pNewCode;
  720.  
  721.     return pItem;
  722.  
  723. }
  724.  
  725.  
  726. // ----------------------------------------------------------------------------
  727. // This Function is used to de-allocate memory in a InputStructure.
  728. // A destructor wasn't used becuase other objects may also own the
  729. // same memory.
  730. //
  731. // Parameters:
  732. // pDelStruct : Pointer to a dynamically allocated InputStructure within
  733. //              string data allocated.
  734. //
  735. inline void CleanInputStruct (InputStruct* pDelStruct)
  736. {
  737.     if (pDelStruct != NULL)
  738.     {
  739.         delete pDelStruct -> pData;
  740.         delete pDelStruct;
  741.     }
  742. }
  743.  
  744.  
  745. // ----------------------------------------------------------------------------
  746. // Function is used within function DecodeLine() to de-allocate memory
  747. // that it is currently using. This function is called upon a memory
  748. // allocation failure.
  749. //
  750. // Parameters:
  751. // PDelQueue : Pointer to a QueueList object which in general will contain
  752. //             InputStructures.
  753. // pLineData : Pointer to a string will contain a line of a users input file.
  754. //
  755. void DecodeLineCleanUp (QueueList* pDelQueue, char* pLineData)
  756. {
  757.     // Don't implement destructor as other objects may be using the same
  758.     // memory when using structure in output line processing (simple garbage collection)
  759.     while (pDelQueue->status() > 0)
  760.         CleanInputStruct ( ((InputStruct*)pDelQueue -> takeNext()) );
  761.  
  762.     delete pLineData;
  763. }
  764.  
  765.  
  766. // ----------------------------------------------------------------------------
  767. // This function is a single pass decoder for a line of input code that
  768. // is read from the user's input file. The function stores each part of a line,
  769. // be it a comment (with is attributes), code, open brace, close brace, or
  770. // blank line as a InputStructure, each InputStructure is stored within
  771. // a Queue Object.
  772. //
  773. // Parameters:
  774. // pLineData  : Pointer to a line of a users input file (string).
  775. // CComments  : This variable is used to test if the current line is
  776. //              a C type comment (i.e multi-line comment). True value
  777. //              indicated Currently in C comment extraction mode, else
  778. //              in normal extraction mode.
  779. // QueueList* : Pointer to a QueueList object will contains all of
  780. //              a lines basic elements. If this object doesn't contain
  781. //              any elements, then it sugguests there was a processing
  782. //              problem.
  783. //
  784. // Return Values:
  785. // int        : returns a error code.
  786. //              -1 : Memory allocation failure
  787. //               0 : No Worries
  788. //
  789. int DecodeLine (char* pLineData, Boolean& CComments, QueueList* pInputQueue)
  790. {
  791.     // define block seperator chars
  792.     const char* pOpenBrace     = "{";
  793.     const char* pCloseBrace    = "}";
  794.  
  795.     char*      pSChar = NULL; // used to find the starting location of certain elements in a string
  796.     char*      pEChar = NULL; // used as a terminator of an element in a string !
  797.  
  798.  
  799.     // remove unwanted space chars ????
  800.     // pLineData = StripSpacingLeftRight (pLineData);
  801.  
  802.     // @@@@@@ C Comment processing, if over multiple lines @@@@@@
  803.     if (CComments == True)
  804.     {
  805.  
  806.         //#### Test to see if end terminating C comment has arrived !
  807.         pSChar = strstr (pLineData, "*/");
  808.  
  809.         if (pSChar != NULL)
  810.         {
  811.             pSChar[1] = NULLC;   //#### make temp string !
  812.             char* pNewComment =  new char[strlen (pLineData) + 2];
  813.  
  814.             //#### Test if memory allocated
  815.             if (pNewComment == NULL)
  816.             {
  817.                 DecodeLineCleanUp (pInputQueue, pLineData);
  818.                 return -1;
  819.             }
  820.  
  821.             pNewComment        = strcpy (pNewComment, pLineData);
  822.             int len            = strlen (pNewComment);
  823.             pNewComment[len]   = '/';
  824.             pNewComment[len+1] = NULLC;
  825.  
  826.             pSChar += 2;                //##### Advance two mem locations to the right
  827.             strcpy (pLineData, pSChar); //##### Shift left string from current pos
  828.  
  829.             //#### create new queue structure !
  830.             InputStruct* pItem = new InputStruct();
  831.  
  832.             //#### Test if memory allocated
  833.             if (pItem != NULL)
  834.             {
  835.                 pItem -> pData    = pNewComment;
  836.                 pItem -> dataType = CCom;      // comment
  837.                 pItem -> attrib   = False;     // comment without code, even if it has some !
  838.  
  839.                 pInputQueue->putLast (pItem);
  840.             }
  841.             else
  842.             {
  843.                 DecodeLineCleanUp (pInputQueue, pLineData);
  844.                 return -1;
  845.             }
  846.  
  847.             CComments = False;                 //##### No more C like comments
  848.  
  849.         }
  850.         else //##### Place output as comment without code (C comment terminator not found)
  851.         {
  852.             InputStruct* pTemp = ExtractCode (pLineData, CCom, False); // don't remove spaces !
  853.  
  854.             //#### Test if memory allocated
  855.             if (pTemp != NULL)
  856.             {
  857.                 pInputQueue->putLast (pTemp);
  858.                 delete pLineData;
  859.             }
  860.             else
  861.             {
  862.                 DecodeLineCleanUp (pInputQueue, pLineData);
  863.                 return -1;
  864.             }
  865.  
  866.             return 0;
  867.         }
  868.  
  869.  
  870.     }// if multi-line C style comments
  871.  
  872.     
  873.     // N.B Place this function here as to sure not to currupt relative pointer
  874.     // settings that may be used within pLinedata, and become altered through 
  875.     // using this routine.     
  876.     pLineData = StripSpacingLeftRight (pLineData); 
  877.     
  878.     //@@@@@@ Extract /* comment */ C type comments on one line
  879.     pSChar = strstr (pLineData, "/*");  // find start of C Comment
  880.     if (pSChar != NULL)
  881.     {
  882.         //##### Check is "/*" arn't within quotes
  883.         if ((CheckCharsWithinQuotes (pSChar, pSChar+1, pLineData) == False) &&
  884.             (CheckCharsNotCppComments (pSChar, pLineData) == False))
  885.         {
  886.             //##### Check if there is a ending "*/" C terminator comment string
  887.             pEChar = strstr (pLineData, "*/");
  888.  
  889.             //##### If NULL then comments are on multiple lines !
  890.             if (pEChar == NULL)
  891.             {
  892.                 char* pNewComment = new char[strlen (pSChar)+1];
  893.  
  894.                 //#### Test if memory allocated
  895.                 if (pNewComment == NULL)
  896.                 {
  897.                     DecodeLineCleanUp (pInputQueue, pLineData);
  898.                     return -1;
  899.                 }
  900.  
  901.                 pNewComment = strcpy (pNewComment, pSChar);
  902.                 *pSChar  = NULLC; //##### Make it NULL so that comment is removed, from Line
  903.  
  904.                 InputStruct* pItem = new InputStruct();
  905.  
  906.                 //#### Test if memory allocated
  907.                 if (pItem != NULL)
  908.                 {
  909.                     pItem -> pData    = pNewComment;
  910.                     pItem -> dataType = CCom;       // Comment
  911.                     pItem -> attrib   = False;
  912.                     // make multi-line C style comments totally seperate
  913.                     // from code to avoid some likely errors occuring if they
  914.                     // are shifted due to being over written by code.
  915.  
  916.                     // apply recursion so that comment is last item placed
  917.                     // in queue !
  918.                     if (DecodeLine (pLineData, CComments, pInputQueue) != 0)
  919.                     {
  920.                         // problems !
  921.                         delete pItem -> pData;
  922.                         delete pItem;
  923.                         return -1;
  924.                     }
  925.                     else
  926.                         pInputQueue->putLast (pItem);
  927.  
  928.                     //##### Set multi-line comment variable on
  929.                     CComments = True;
  930.  
  931.                     return 0; // no need to continue processing
  932.                 }
  933.                 else
  934.                 {
  935.                     DecodeLineCleanUp (pInputQueue, pLineData);
  936.                     return -1;
  937.                 }
  938.             }
  939.             else
  940.             {
  941.                 pEChar[1] = NULLC; //##### make temp string !
  942.                 char* pNewComment =  new char[strlen (pSChar) + 2];
  943.  
  944.                 //#### Test if memory allocated
  945.                 if (pNewComment == NULL)
  946.                 {
  947.                     DecodeLineCleanUp (pInputQueue, pLineData);
  948.                     return -1;
  949.                 }
  950.  
  951.                 pNewComment        = strcpy (pNewComment, pSChar);
  952.                 int len            = strlen (pNewComment);
  953.                 pNewComment[len]   = '/';
  954.                 pNewComment[len+1] = NULLC;
  955.  
  956.                 pEChar += 2;      //##### Advance two memory locs to the right
  957.                 strcpy (pSChar, pEChar);
  958.  
  959.                 InputStruct* pItem = new InputStruct();
  960.                 //#### Test if memory allocated
  961.                 if (pItem != NULL)
  962.                 {
  963.                     pItem -> pData    = pNewComment;
  964.                     pItem -> dataType = CCom;                        // Comment
  965.                     pItem -> attrib   = TestLineHasCode (pLineData); // Comment without code ?
  966.  
  967.                     pInputQueue->putLast (pItem);
  968.  
  969.                 }
  970.                 else
  971.                 {
  972.                     DecodeLineCleanUp (pInputQueue, pLineData);
  973.                     return -1;
  974.                 }
  975.  
  976.             } //##### else
  977.  
  978.         } //##### If comment not within quotes
  979.  
  980.     }//##### If "/*" C comments pressent
  981.     
  982.     //##### Remove blank spacing from left & right of string
  983.     pLineData = StripSpacingLeftRight (pLineData);
  984.  
  985.     //@@@@@@ C++ Comment Processing !
  986.     pSChar = strstr (pLineData, "//");
  987.     if (pSChar != NULL)
  988.     {
  989.         //##### Check if "//" arn't within quotes, if false then it's a comment
  990.         if (CheckCharsWithinQuotes (pSChar, pSChar+1, pLineData) == False)
  991.         {
  992.             char* pNewComment =  new char[strlen (pSChar) + 1];
  993.  
  994.             //#### Test if memory allocated
  995.             if (pNewComment == NULL)
  996.             {
  997.                 DecodeLineCleanUp (pInputQueue, pLineData);
  998.                 return -1;
  999.             }
  1000.  
  1001.             // copy comment into allocated memory
  1002.             strcpy (pNewComment, pSChar);
  1003.             *pSChar  = NULLC;                   //##### Terminate original string !
  1004.  
  1005.             //#### create new queue structure !
  1006.             InputStruct* pItem = new InputStruct();
  1007.             //#### Test if memory allocated
  1008.             if (pItem != NULL)
  1009.             {
  1010.                 pItem -> pData    = pNewComment;
  1011.                 pItem -> dataType = CppCom;                      // Comment
  1012.                 pItem -> attrib   = TestLineHasCode (pLineData); // Comment without code ?
  1013.  
  1014.                 pInputQueue->putLast (pItem);
  1015.  
  1016.             }
  1017.             else
  1018.             {
  1019.                 DecodeLineCleanUp (pInputQueue, pLineData);
  1020.                 return -1;
  1021.             }
  1022.         }
  1023.     }
  1024.  
  1025.     //@@@@@@ #define (preprocessor extraction)
  1026.     if (pLineData[0] == '#')
  1027.     {
  1028.         //#### create new queue structure !
  1029.         InputStruct* pItem = new InputStruct();
  1030.  
  1031.         //#### Test if memory allocated
  1032.         if (pItem != NULL)
  1033.         {
  1034.             pItem -> pData    = pLineData;
  1035.             pItem -> dataType = PreP;                            // preprocessor
  1036.             pInputQueue->putLast (pItem);
  1037.  
  1038.         }
  1039.         else
  1040.         {
  1041.             DecodeLineCleanUp (pInputQueue, pLineData);
  1042.             return -1;
  1043.         }
  1044.  
  1045.         return 0; // no worries !
  1046.     }
  1047.  
  1048.     //################# Actual Code Extraction #################
  1049.  
  1050.     pLineData = StripSpacingLeftRight (pLineData);
  1051.     
  1052.     //@@@@@@ Test whats left in line for "{", and "}" braces
  1053.  
  1054.     pSChar = pLineData-1;
  1055.  
  1056.     for (;;)
  1057.     {
  1058.         pSChar = strstr (pSChar+1, pOpenBrace);
  1059.  
  1060.         if (pSChar != NULL)
  1061.         {
  1062.            if (CheckCharsWithinQuotes (pSChar, pSChar, pLineData) == False)
  1063.                break;
  1064.            // else continue and try and find next one after comment !
  1065.         }
  1066.         else
  1067.             break;
  1068.     }
  1069.  
  1070.     pEChar = pLineData -1;
  1071.  
  1072.     for (;;)
  1073.     {
  1074.         pEChar = strstr (pEChar+1, pCloseBrace);
  1075.  
  1076.         if (pEChar != NULL)
  1077.         {
  1078.            if (CheckCharsWithinQuotes (pEChar, pEChar, pLineData) == False)
  1079.                break;
  1080.            // else continue and try and find next one after comment !
  1081.         }
  1082.         else
  1083.             break;
  1084.     }
  1085.  
  1086.     //##### check if braces arn't within quotes, if so .. then ignore!
  1087.  
  1088.     Boolean testEnumType = False;
  1089.     if ( ((pSChar != NULL) && (pEChar != NULL)) && (pSChar < pEChar))
  1090.     {
  1091.         // test to see if there are multiple open/ close braces in enum
  1092.         // select tive range
  1093.         // i.e. { if ( a == b ) { b = c } else { d = e } }
  1094.         char* pOBrace = pSChar;
  1095.  
  1096.         for (;;)
  1097.         {
  1098.             pOBrace = strstr (pOBrace+1, pOpenBrace);
  1099.  
  1100.             if (pOBrace != NULL)
  1101.             {
  1102.                 if (CheckCharsWithinQuotes (pOBrace, pOBrace, pLineData) == False)
  1103.                    break;
  1104.                 // else continue and try and find next one after comment !
  1105.             }
  1106.             else
  1107.                 break;
  1108.         }
  1109.  
  1110.         if ( (pOBrace == NULL) || ((pOBrace > pEChar) && (pOBrace != NULL)) )
  1111.                 testEnumType = True;
  1112.     }
  1113.  
  1114.     //##### If condition correct, then make rest of line just code ! (e.g enum)
  1115.     // if no items in input queue, and no multiple open, close braces in
  1116.     // line then .... extract as enum.
  1117.     if ( (testEnumType != False) && (pInputQueue -> status () <= 0) )
  1118.     {
  1119.         //store code as enum type if follow if condition is true
  1120.         pEChar++;
  1121.  
  1122.         if (*pEChar == ';') // advance another char
  1123.                 pEChar++;
  1124.             
  1125.         char BackUp = *pEChar;
  1126.         *pEChar     = NULLC;
  1127.  
  1128.         InputStruct* pTemp = ExtractCode(pLineData);
  1129.         if (pTemp == NULL)
  1130.         {
  1131.             DecodeLineCleanUp (pInputQueue, pLineData);
  1132.             return -1;
  1133.         }
  1134.  
  1135.         pInputQueue->putLast (pTemp);
  1136.  
  1137.         *pEChar   = BackUp;
  1138.         strcpy (pLineData, pEChar);
  1139.  
  1140.         // restart decoding line !
  1141.         return DecodeLine (pLineData, CComments, pInputQueue);
  1142.         // end of recursive call !
  1143.  
  1144.     } // if '{' and '}' exit on same line
  1145.  
  1146.     //##### Determine extraction precedence !
  1147.     if ((pSChar != NULL) && (pEChar != NULL))
  1148.     {
  1149.         if (pSChar > pEChar)
  1150.             pSChar = NULL;
  1151.         else
  1152.             pEChar = NULL;
  1153.     }
  1154.  
  1155.     //##### Place whatever is before the open brace "{", or "}" as code
  1156.     if ((pSChar != NULL) || (pEChar != NULL))
  1157.     {
  1158.         char backUp;
  1159.  
  1160.         if (pSChar != NULL)
  1161.         {
  1162.             backUp         = *pSChar;
  1163.             *pSChar        = NULLC;
  1164.         }
  1165.         else
  1166.         {
  1167.             backUp = *pEChar;
  1168.             *pEChar        = NULLC;
  1169.         }
  1170.  
  1171.         //#### Store leading code if any
  1172.         if (TestLineHasCode (pLineData) != False)
  1173.         {
  1174.            char* pTemp = new char [strlen (pLineData) +1];
  1175.            if (pTemp == NULL)
  1176.            {
  1177.                 DecodeLineCleanUp (pInputQueue, pLineData);
  1178.                 return -1;
  1179.            }
  1180.  
  1181.            //#### strip spacing is handled within extractCode routine. This
  1182.            //#### means that pointers that are calculated before stripSpacing function
  1183.            //#### remain valid.
  1184.  
  1185.            pTemp = strcpy (pTemp, pLineData);
  1186.            InputStruct* pLeadCode = ExtractCode (pTemp);
  1187.  
  1188.            if (pLeadCode == NULL)
  1189.            {
  1190.                 DecodeLineCleanUp (pInputQueue, pLineData);
  1191.                 return -1;
  1192.            }
  1193.  
  1194.            pInputQueue->putLast (pLeadCode);
  1195.            delete pTemp;
  1196.         }
  1197.  
  1198.         //##### Update main string
  1199.         if (pSChar != NULL)
  1200.         {
  1201.            *pSChar        = backUp;
  1202.            pLineData      = strcpy (pLineData, pSChar);
  1203.         }
  1204.         else
  1205.         {
  1206.            *pEChar        = backUp;
  1207.            pLineData      = strcpy (pLineData, pEChar);
  1208.         }
  1209.  
  1210.         // extract open/closing brace from code, and place brace as seperate
  1211.         // line from code. And create new structure for code
  1212.         InputStruct* pTemp;
  1213.         int          extractMode;
  1214.  
  1215.         if (pLineData[0] == '{')
  1216.             extractMode = 1; // remove open brace
  1217.         else
  1218.             extractMode = 2; // remove close brace
  1219.  
  1220.         do
  1221.         {
  1222.             switch (extractMode)
  1223.             {
  1224.                 case (1):    // remove open brace
  1225.                 {
  1226.                     backUp       = pLineData[1]; // contain a char, or NULLC char
  1227.                     pLineData[1] = NULLC;
  1228.                     pTemp        = ExtractCode (pLineData, OBrace);//##### Define data type before storing
  1229.                     //#### update string
  1230.                     pLineData[1] = backUp;
  1231.  
  1232.                     strcpy (pLineData, pLineData+1);
  1233.                     extractMode  = 3;            // apply recursive extraction
  1234.  
  1235.                     break;
  1236.                 }
  1237.  
  1238.                 case (2):   // remove close brace
  1239.                 {
  1240.                     // test the type of close brace extraction !
  1241.                     // check for following code ...
  1242.                     // struct { int a, b, } aStructure;
  1243.                     //@@@@@@ Test whats left in line for "{", and "}" braces
  1244.  
  1245.                     // start one after first char !
  1246.                     pSChar = pLineData;
  1247.                     for (;;)
  1248.                     {
  1249.                         pSChar = strstr (pSChar+1, pOpenBrace);
  1250.  
  1251.                         if (pSChar != NULL)
  1252.                         {
  1253.                             if (CheckCharsWithinQuotes (pSChar, pSChar, pLineData) == False)
  1254.                                break;
  1255.                             // else continue and try and find next one after comment !
  1256.                         }
  1257.                         else
  1258.                             break;
  1259.                     }
  1260.  
  1261.                     pEChar = pLineData;
  1262.                     for (;;)
  1263.                     {
  1264.                         pEChar = strstr (pEChar+1, pCloseBrace);
  1265.  
  1266.                         if (pEChar != NULL)
  1267.                         {
  1268.                             if (CheckCharsWithinQuotes (pEChar, pEChar, pLineData) == False)
  1269.                                break;
  1270.                             // else continue and try and find next one after comment !
  1271.                         }
  1272.                         else
  1273.                             break;
  1274.                     }
  1275.  
  1276.                     if ((pSChar != NULL) || (pEChar != NULL))
  1277.                     {
  1278.                         if (pLineData[1] == ';')     // if true, extract after char
  1279.                             pEChar        = pLineData+2;
  1280.                         else
  1281.                             pEChar        = pLineData+1;
  1282.  
  1283.                         backUp            = *pEChar;
  1284.                         *pEChar           = NULLC;
  1285.  
  1286.                         pTemp = ExtractCode (pLineData, CBrace);
  1287.                         // #### update string;
  1288.                         *pEChar           = backUp;
  1289.                         strcpy (pLineData, pEChar);
  1290.  
  1291.                         extractMode       = 3;       // apply recursive extraction
  1292.                     }
  1293.                     else // rest of data is considered as code !
  1294.                     {
  1295.                         pTemp     = ExtractCode (pLineData, CBrace);
  1296.                         pLineData = NULL;            // leave processing !
  1297.                     }
  1298.                     break;
  1299.                 }
  1300.  
  1301.                 case (3):   // remove what is left on line as code.
  1302.                 {
  1303.                     return DecodeLine (pLineData, CComments, pInputQueue);
  1304.                     // end of recursive call !
  1305.                 }
  1306.             }// switch;
  1307.  
  1308.             //#### Test if memory allocated
  1309.             if (pTemp == NULL)
  1310.             {
  1311.                 DecodeLineCleanUp (pInputQueue, pLineData);
  1312.                 return -1;
  1313.             }
  1314.  
  1315.             pInputQueue->putLast (pTemp); // store Item
  1316.  
  1317.         } while ((TestLineHasCode (pLineData) != False) && (pTemp != NULL));
  1318.  
  1319.     }
  1320.  
  1321.     else //##### Line contains either code, or spacing
  1322.     {
  1323.         //##### If nothing in string, and nothing stored in queue, then blank line
  1324.         if ((pLineData[0] == NULLC) && ((pInputQueue->status()) <= 0))
  1325.         {
  1326.             //##### implement blank space
  1327.             InputStruct* pTemp = ExtractCode (pLineData, ELine);
  1328.  
  1329.             if (pTemp != NULL)
  1330.                 pInputQueue->putLast (pTemp);
  1331.             else
  1332.             {
  1333.                 DecodeLineCleanUp (pInputQueue, pLineData);
  1334.                 return -1;
  1335.             }
  1336.         }
  1337.         //##### If line has more than spacing/tabs then code
  1338.         else if (TestLineHasCode (pLineData) != False)
  1339.              {
  1340.                   // implement blank space
  1341.                   InputStruct* pTemp = ExtractCode (pLineData);
  1342.  
  1343.                   if (pTemp != NULL)
  1344.                      pInputQueue->putLast (pTemp);
  1345.                   else
  1346.                   {
  1347.                       DecodeLineCleanUp (pInputQueue, pLineData);
  1348.                       return -1;
  1349.                   }
  1350.              }
  1351.     }
  1352.     
  1353.     //##### Final cleanup before returning queue with line elements
  1354.     delete pLineData;
  1355.     return 0;  // no worries
  1356. }
  1357.  
  1358.  
  1359. // ----------------------------------------------------------------------------
  1360. // Function takes a QueueList object that contains InputStructure items, and
  1361. // uses these items to reconstuct a compressed version of a output line of
  1362. // code, comment, or both.
  1363. //
  1364. // Parameters:
  1365. // indentStack : Variable used to show how many spaces/tabs to indent when
  1366. //              creating a new OutputStructure.
  1367. // pInputQueue : Pointer to the InputStructure queue object.
  1368. // pOutputQueue: Pointer to the OutputStructure queue object.
  1369. // userS       : Structure that contains the users config settings.
  1370. //
  1371. // Return Values:
  1372. // int           : Return values of ...
  1373. //         0 = No problems
  1374. //        -1 = Memory allocation failure
  1375. //        -2 = Line construction error, unexpected type found.
  1376. int ConstructLine (int& indentStack, QueueList* pInputQueue, QueueList* pOutputQueue, Config userS)
  1377. {
  1378.     InputStruct* pTestType = NULL;
  1379.  
  1380.     while ( pInputQueue->status() > 0 )
  1381.     {
  1382.         pTestType = (InputStruct*) pInputQueue -> takeNext();
  1383.  
  1384.         switch (pTestType -> dataType)
  1385.         {
  1386.             //@@@@@@@ Processing of C type comments /* comment */
  1387.             case (CCom):
  1388.             //@@@@@@@ Processing of C++ type comments // comment
  1389.             case (CppCom):
  1390.             {
  1391.                 if (pTestType -> attrib == True)  //##### If true then comment has code
  1392.                 {
  1393.                     OutputStruct* pOut = new OutputStruct;
  1394.  
  1395.                     // ##### Memory allocation test
  1396.                     if (pOut != NULL)
  1397.                     {
  1398.                         // ##### store current comment in output structure
  1399.                         pOut -> pComment      = pTestType -> pData;
  1400.                         delete pTestType;     //#### free memory
  1401.  
  1402.                         // ##### getnext Item
  1403.                         pTestType = (InputStruct*) pInputQueue -> takeNext();
  1404.  
  1405.                         // ##### Type Checking !!!!!
  1406.                         // if nothing in queue, or next item isn't code then some sort of error
  1407.                         if ((pTestType == NULL) || ((pTestType -> dataType <= CppCom) || (pTestType -> dataType >= ELine)))
  1408.                         {
  1409.                             fprintf (stderr, "\n#### ERROR ! Error In Line Construction !");
  1410.                             fprintf (stderr, "\nExpected Some Sort Of Code ! Data Type Found = ");
  1411.                             if (pTestType == NULL)
  1412.                                 fprintf (stderr, "NULL");
  1413.                             else
  1414.                                 fprintf (stderr, "%d", pTestType -> dataType);
  1415.                             return -2;      // ##### incorrect dataType expected!
  1416.                         }
  1417.                         else // place code in line structure, calculate indenting !
  1418.                         {
  1419.  
  1420.                             // if pData length overwrites comments then place comments on newline
  1421.                             if ( (indentStack + strlen (pTestType -> pData)) > (userS.posOfCommentsWC) )
  1422.                             {
  1423.                                 pOut -> filler = userS.posOfCommentsWC;
  1424.                                 pOutputQueue -> putLast (pOut);
  1425.  
  1426.                                 // create new output line structure
  1427.                                 pOut = new OutputStruct();
  1428.                                 if (pOut == NULL)
  1429.                                    return -1; //##### Memory Allocation error
  1430.                             }
  1431.  
  1432.                             switch (pTestType -> dataType)
  1433.                             {
  1434.                                 case (Code):
  1435.                                 case (PreP):
  1436.                                 {
  1437.                                     pOut -> indentSpace = indentStack;
  1438.                                     pOut -> pCode  = pTestType -> pData;
  1439.  
  1440.                                     // if comment wasn't placed on a newline due to code overwriting comment
  1441.                                     if (pOut -> pComment != NULL)
  1442.                                         pOut -> filler = (userS.posOfCommentsWC - (indentStack + strlen (pTestType -> pData)));
  1443.  
  1444.                                     break;
  1445.                                 }
  1446.  
  1447.                                 case (OBrace):
  1448.                                 case (CBrace):
  1449.                                 {
  1450.  
  1451.                                     // indent back before adding brace, some error checking
  1452.                                     if ((pTestType -> dataType == CBrace) && (indentStack > 0))
  1453.                                     {
  1454.                                         indentStack -= userS.tabSpaceSize;
  1455.  
  1456.                                         // if comment wasn't placed on a newline due to code overwriting comment
  1457.                                         if (pOut -> pComment != NULL)
  1458.                                                pOut -> filler = (userS.posOfCommentsWC - (indentStack + strlen (pTestType -> pData)));
  1459.                                     }
  1460.  
  1461.                                     // load input data into the approiate place in output structure
  1462.                                     pOut -> indentSpace = indentStack;
  1463.                                     pOut -> pBrace = pTestType -> pData;
  1464.  
  1465.                                     // adjust indentation if next output line is a open Brace
  1466.                                     if (pTestType -> dataType == OBrace)
  1467.                                     {
  1468.                                           // if comment wasn't placed on a newline due to code overwriting comment
  1469.                                           if (pOut -> pComment != NULL)
  1470.                                                      pOut -> filler = (userS.posOfCommentsWC - (indentStack + strlen (pTestType -> pData)));
  1471.  
  1472.                                           indentStack += userS.tabSpaceSize;
  1473.                                     }
  1474.  
  1475.                                     break;
  1476.                                 }
  1477.  
  1478.                             }// switch
  1479.  
  1480.  
  1481.                             pOutputQueue -> putLast (pOut);
  1482.                         }// else
  1483.  
  1484.                     }
  1485.                     else
  1486.                         return -1; //##### Memory allocation error
  1487.                 }
  1488.                 else
  1489.                 {
  1490.                     OutputStruct* pOut = new OutputStruct();
  1491.  
  1492.                     // ##### Memory allocation test
  1493.                     if (pOut != NULL)
  1494.                     {
  1495.                         // JZAS Start
  1496.                         if (userS.leaveCommentsNC != False)
  1497.                             pOut -> indentSpace   = indentStack;
  1498.                         else
  1499.                               pOut -> indentSpace   = userS.posOfCommentsNC;
  1500.                         // JZAS End
  1501.                         
  1502.                         pOut -> pComment          = pTestType -> pData;
  1503.                         pOutputQueue -> putLast (pOut);
  1504.                     }
  1505.                     else
  1506.                         return -1; //##### Memory allocation error
  1507.  
  1508.                 }// else a comment without code !
  1509.  
  1510.                 break;
  1511.             }// case
  1512.  
  1513.             // @@@@@@ Processing of code (i.e k = 1; enum show {one, two};)
  1514.             case (Code):
  1515.             {
  1516.                 OutputStruct* pOut = new OutputStruct();
  1517.                 if (pOut != NULL)
  1518.                 {
  1519.                     pOut -> indentSpace     = indentStack;
  1520.                     pOut -> pCode           = pTestType -> pData;
  1521.                     pOutputQueue -> putLast (pOut);
  1522.                 }
  1523.                 else
  1524.                     return -1; //##### Memory allocation error
  1525.  
  1526.                 break;
  1527.             }
  1528.  
  1529.             // @@@@@@ Processing of open brackets "{ k = 1;"
  1530.             case (OBrace):
  1531.             // @@@@@@ Processing of closed brackets "} k = 1;"
  1532.             case (CBrace):
  1533.             {
  1534.                 OutputStruct* pOut = new OutputStruct();
  1535.                 if (pOut != NULL)
  1536.                 {
  1537.                     // indent back before adding brace, some error checking
  1538.                     if ((pTestType -> dataType == CBrace) && (indentStack > 0))
  1539.                         indentStack -= userS.tabSpaceSize;
  1540.  
  1541.                     pOut -> indentSpace     = indentStack;
  1542.                     pOut -> pBrace          = pTestType -> pData;
  1543.                     pOutputQueue -> putLast (pOut);
  1544.  
  1545.                     // ##### advance to the left, adjust indentation !
  1546.                     if (pTestType -> dataType == OBrace)
  1547.                         indentStack += userS.tabSpaceSize;
  1548.                 }
  1549.                 else
  1550.                     return -1; //##### Memory allocation error
  1551.  
  1552.                 break;
  1553.             }
  1554.  
  1555.             // @@@@@@ Blank Line spacing
  1556.             case (ELine):
  1557.             {
  1558.                 OutputStruct* pOut = new OutputStruct();
  1559.                 if (pOut != NULL)
  1560.                     pOutputQueue -> putLast (pOut);      //#### Place NULL line in output queue
  1561.                 else
  1562.                     return NULL; //##### Memory allocation error
  1563.  
  1564.                 break;
  1565.             }
  1566.             // @@@@@@ Preprocessor Line !
  1567.             case (PreP):
  1568.             {
  1569.                 OutputStruct* pOut = new OutputStruct();
  1570.                 if (pOut != NULL)
  1571.                 {
  1572.                     pOut -> pCode       = pTestType -> pData;
  1573.                     pOut -> indentSpace = 0;
  1574.                     pOutputQueue -> putLast (pOut);      //#### Place NULL line in output queue
  1575.                 }
  1576.                 else
  1577.                     return NULL; //##### Memory allocation error
  1578.  
  1579.                 break;
  1580.             }
  1581.  
  1582.         } // switch
  1583.  
  1584.         delete pTestType; // ##### Remove structure from memory, not it's data
  1585.                           // ##### it contained (i.e char* pData), this is stored
  1586.                           // ##### in the output queue.
  1587.  
  1588.     } // while there are items to construct !
  1589.  
  1590.     return 0;
  1591.  
  1592. }
  1593.  
  1594.  
  1595. // ----------------------------------------------------------------------------
  1596. // This function is used to allocate memory for indentation within function
  1597. // OutputToOutFile(). Once the memory needed is allocated, it fills the memory
  1598. // with spaces, or tabs depending upon the fill mode.
  1599. //
  1600. // Parameters:
  1601. // Mode         : Defines the fill mode of the memory that it allocate
  1602. //             1 = tabs only
  1603. //             2 = spaces only
  1604. //             3 = both
  1605. // len       : Number of bytes needed to be allocated
  1606. // spaceIndent:Number of memory locations a tab character take up
  1607. //
  1608. // Return Values:
  1609. // char*     : Returns a pointer to the memory/string that was allocated
  1610. //
  1611. char* TabSpacing (int mode, int len, int spaceIndent)
  1612. {
  1613.     char* pOutTab = NULL;
  1614.     char* pOutSpc = NULL;
  1615.  
  1616.     if ((mode & 1) == 1)
  1617.     {
  1618.         int numOfTabs = 0;
  1619.  
  1620.         // bypass exception error
  1621.         if (spaceIndent > 0)
  1622.            numOfTabs = len / spaceIndent;
  1623.  
  1624.         pOutTab = new char[numOfTabs+1];
  1625.         if (pOutTab != NULL)
  1626.         {
  1627.             for (int fillTabs = 0; fillTabs < numOfTabs; fillTabs++)
  1628.                     pOutTab[fillTabs] = TAB;
  1629.             pOutTab[numOfTabs] = NULLC;
  1630.         }
  1631.         else
  1632.             return NULL; // memory allocation failed
  1633.  
  1634.         // If not in both tab, and space concatination.
  1635.         if ((mode & 2) == 0)
  1636.               return pOutTab;
  1637.     }//bit 0 set !
  1638.  
  1639.     if ((mode & 2) == 2)
  1640.     {
  1641.         if (pOutTab == NULL) //##### normal space allocation !
  1642.         {
  1643.             pOutSpc = new char[len+1];
  1644.             if (pOutSpc != NULL)
  1645.             {
  1646.                 for (int fillSpcs = 0; fillSpcs < len; fillSpcs++)
  1647.                     pOutSpc[fillSpcs] = ' ';
  1648.                 pOutSpc[len] = NULLC;
  1649.                 return pOutSpc;   //##### return end product
  1650.             }
  1651.             else
  1652.                     return NULL; // memory allocation failed
  1653.         }
  1654.         else  // else a mix of spaces & tabs
  1655.         {
  1656.             int numOfSpcs = 0;
  1657.  
  1658.             if (spaceIndent > 0)
  1659.                numOfSpcs = len % spaceIndent;
  1660.  
  1661.             pOutSpc = new char[numOfSpcs+1];
  1662.             if (pOutSpc != NULL)
  1663.             {
  1664.                 for (int fillSpcs = 0; fillSpcs < numOfSpcs; fillSpcs++)
  1665.                     pOutSpc[fillSpcs] = ' ';
  1666.                 pOutSpc[numOfSpcs] = NULLC;
  1667.             }
  1668.             else
  1669.                 return NULL; // memory allocation failed
  1670.         }
  1671.     }// bit 1 set
  1672.  
  1673.     //##### Concatinate tabs & spaces
  1674.     if ( ((mode & 1) == 1) && ((mode & 2) == 2) )
  1675.     {
  1676.         char* pConCat = new char[(strlen (pOutTab) + strlen (pOutSpc) + 1)];
  1677.         // #### Check memory allocation
  1678.         if (pConCat == NULL)
  1679.         {
  1680.             delete pOutTab;
  1681.             delete pOutSpc;
  1682.             return NULL;
  1683.         }
  1684.         strcpy (pConCat, pOutTab);
  1685.         strcpy (pConCat + strlen (pConCat), pOutSpc);
  1686.         delete pOutTab;
  1687.         delete pOutSpc;
  1688.         return pConCat;
  1689.     }
  1690.  
  1691.     return NULL; //##### illegal mode passed !
  1692. }
  1693.  
  1694.  
  1695. // ----------------------------------------------------------------------------
  1696. // Function is used to indent single indented code such is found in if, while,
  1697. // else statements. Also handles case like statements within switchs'.
  1698. //
  1699. // Parameters:
  1700. // pLines     : Pointer to the output queue.
  1701. // pIMode     : Pointer to indent type stack.
  1702. // userS      : User configuration (i.e indent spacing, position of comments)
  1703. //
  1704. // Return Values:
  1705. // QueueList*    : Pointer to the output queue (may have been reconstructed),
  1706. //                 returns NULL if failed to allocate memory
  1707. //
  1708. QueueList* IndentNonBraceCode (QueueList* pLines, StackList* pIMode, Config& userS)
  1709. {
  1710.     // Constant used to indent the number of spaces if a single statement is
  1711.     // accross more than one line !
  1712.     const int multLineSingleStat = 3;
  1713.  
  1714.     // if there are items to check !
  1715.     if ((pLines != NULL) && (pLines -> status () <= 0))
  1716.         return pLines;
  1717.  
  1718.     // If there are indent items to process !
  1719.     if (pIMode -> status() <= 0)
  1720.         return pLines;
  1721.  
  1722.     OutputStruct* pAlterLine  = (OutputStruct*) pLines -> peek (1);
  1723.     // A preprocessor command
  1724.     if ((pAlterLine -> pCode != NULL) && (pAlterLine -> pCode[0] == '#'))
  1725.        return pLines;
  1726.  
  1727.     IndentStruct* pIndentItem = (IndentStruct*) pIMode -> pop();
  1728.  
  1729.     if ( ((pAlterLine -> pCode != NULL)     || ((pAlterLine -> pBrace != NULL) && (pIndentItem -> attrib == 2)) ) ||
  1730.          ((userS.leaveCommentsNC != False)  && ((pAlterLine -> pCode == NULL)  && (pAlterLine -> pComment != NULL))) )
  1731.     {
  1732.         switch (pIndentItem -> attrib)
  1733.         {
  1734.             // single indent
  1735.             case (1):
  1736.             {
  1737.                 int indentAmount;
  1738.  
  1739.                 // Test if current code as a ';' char at end of line,
  1740.                 // if so then do full indent, else do 3 char indent!
  1741.                 
  1742.                 if ((pAlterLine -> pCode != NULL) &&
  1743.                     (pAlterLine -> pCode[strlen (pAlterLine -> pCode)-1] != ';'))
  1744.                 {
  1745.                     pIndentItem -> firstPass    = True;
  1746.                     indentAmount = pIndentItem -> singleIndentLen;
  1747.                 }
  1748.                 else if (pIndentItem -> firstPass != False)
  1749.                          indentAmount = (userS.tabSpaceSize << 1);
  1750.                      else
  1751.                          indentAmount = userS.tabSpaceSize;
  1752.  
  1753.                 // Single line indentation calculation
  1754.                 pAlterLine -> indentSpace += indentAmount;
  1755.                 break;
  1756.             }
  1757.  
  1758.             // indent of a case statement !
  1759.             case (2):
  1760.             {
  1761.                 // determine how many case like items are stored within
  1762.                 // list to determine how much to indent !
  1763.                 int Icount  = MultiIndent;
  1764.                 char* pTest = NULL;
  1765.  
  1766.                 pAlterLine -> indentSpace += (userS.tabSpaceSize * (pIMode -> status()));
  1767.  
  1768.                 // test if not another case, or default, if so, dont indent !
  1769.                 if (pAlterLine -> pCode != NULL) // possiblity of a NULL here
  1770.                 {
  1771.                     do
  1772.                     {
  1773.                         pTest = strstr (pAlterLine -> pCode, pIndentWords[Icount]);
  1774.                         Icount++;
  1775.                     } while ((pTest == NULL) && (Icount < IndentWordLen));
  1776.                 }
  1777.  
  1778.                 // check for closing braces to end case indention
  1779.                 if ((pTest == NULL) && (pAlterLine -> pBrace != NULL))
  1780.                 {
  1781.                     if ((*(pAlterLine -> pBrace) == '}') && (pAlterLine -> indentSpace == pIndentItem -> pos))
  1782.                     {
  1783.                         delete pIndentItem;
  1784.                         pIndentItem = NULL;
  1785.                     }
  1786.                 }
  1787.  
  1788.                 // indent as per normal !
  1789.                 if ((pIndentItem != NULL) && (pTest == NULL))
  1790.                 {
  1791.                     pIMode -> push (pIndentItem); // ok to indent next item !
  1792.                     pAlterLine -> indentSpace += userS.tabSpaceSize;
  1793.                 }
  1794.                 else if (pIndentItem != NULL)
  1795.                 {
  1796.                     // if end single indent keyword found, check to see
  1797.                     // whether it is the correct one before removing it !
  1798.                     if ((pTest != NULL) && (pIndentItem -> pos+userS.tabSpaceSize < pAlterLine -> indentSpace))
  1799.                     {
  1800.                         pIMode -> push (pIndentItem); // ok to indent next item !
  1801.                         pAlterLine -> indentSpace += userS.tabSpaceSize;
  1802.                     }
  1803.                     else
  1804.                     {
  1805.                         delete pIndentItem;
  1806.                         pIndentItem = NULL;
  1807.                     }
  1808.                 }
  1809.                 break;
  1810.             }
  1811.  
  1812.         }// switch
  1813.  
  1814.         // test if code has started to overwrite comments, and
  1815.         // not a case, or default statement ... if so, adjust queue !
  1816.         if ( ((pAlterLine -> pComment != NULL) && (pIndentItem != NULL)) &&
  1817.              ((pAlterLine -> pCode    != NULL) || (pAlterLine -> pBrace != NULL)) )
  1818.         {
  1819.             // alter filler size for comment spacing !
  1820.             pAlterLine -> filler -= userS.tabSpaceSize;
  1821.  
  1822.             // if less than 0, then code is overwriting comments !
  1823.             if (pAlterLine -> filler < 0)
  1824.             {
  1825.                 // reconstruct queue !
  1826.                 QueueList*    pNewQueue = new QueueList();
  1827.                 OutputStruct* pNewItem  = new OutputStruct();
  1828.                 pAlterLine              = (OutputStruct*) pLines -> takeNext();
  1829.  
  1830.                 if (pNewItem == NULL)
  1831.                 {
  1832.                     delete pNewQueue;
  1833.                     delete pIMode;
  1834.                     delete pLines;
  1835.                     return NULL;// out of memory
  1836.                 }
  1837.  
  1838.                 // load new structure
  1839.                 pNewItem   -> filler      = userS.posOfCommentsWC;
  1840.                 pNewItem   -> pComment    = pAlterLine -> pComment;
  1841.                 pAlterLine -> filler      = 0; // set this to zero as not to create filler
  1842.                                                // spaces at line output time.
  1843.                 pAlterLine -> pComment    = NULL;
  1844.  
  1845.                 // reconstruct queue !
  1846.                 pNewQueue -> putLast (pNewItem);
  1847.                 pNewQueue -> putLast (pAlterLine);
  1848.  
  1849.                 // copy existing lines from old queue, into the newly created queue !
  1850.                 while (pLines -> status () > 0)
  1851.                       pNewQueue -> putLast ( pLines -> takeNext() );
  1852.  
  1853.                 delete pLines;
  1854.                 pLines = pNewQueue; // reassign new queue object
  1855.  
  1856.             } // if over writting comments
  1857.         }// if comments exist on same line as code
  1858.  
  1859.         // Remove single line indentation from memory, if current line
  1860.         // does contain a if, else, while ... type keyowrd
  1861.         if ((pIndentItem != NULL) && (pIndentItem -> attrib == 1))
  1862.         {
  1863.             // recursive function call !
  1864.             if (pIMode -> status() > 0)
  1865.                 pLines = IndentNonBraceCode (pLines, pIMode, userS);
  1866.  
  1867.             pIMode -> push (pIndentItem);
  1868.             pIndentItem = NULL;
  1869.         }
  1870.  
  1871.     } // if code to process
  1872.     else if (pIndentItem != NULL)
  1873.         // no indentation yet, maybe only blank line, or comment in case
  1874.         pIMode -> push (pIndentItem);
  1875.  
  1876.     return pLines;
  1877. }
  1878.  
  1879.  
  1880. // ----------------------------------------------------------------------------
  1881. // Function allocates indent structures used to indent code that don't lie
  1882. // within braces, but should still be indented.
  1883. //
  1884. // Parameters:
  1885. // pIMode     : Pointer to a indent stack. Contains indent structures used to
  1886. //              indent code without braces
  1887. // pLines     : Pointer to output queue, stores semi-finished output code.
  1888. // userS      : User settings.
  1889. //
  1890. // Return Values:
  1891. // QueueList*    : Pointer to the output queue (may have been reconstructed),
  1892. //                 returns NULL if failed to allocate memory
  1893. //
  1894. QueueList* IndentNonBraces (StackList* pIMode, QueueList* pLines, Config userS)
  1895. {
  1896.     const int minLimit = 2;             // used in searching output queue
  1897.                                         // for open braces
  1898.     // indent Items contained !
  1899.     if (pIMode -> status () > 0)
  1900.     {
  1901.          char*         pBraceOnNewLn = ((OutputStruct*) pLines -> peek (1)) -> pBrace;
  1902.          char*         pBraceOnCurLn = ((OutputStruct*) pLines -> peek (1)) -> pCode;
  1903.          IndentStruct* pTestBrace = (IndentStruct*) pIMode -> pop();
  1904.  
  1905.          if ( (pBraceOnNewLn != NULL) &&
  1906.               ((pBraceOnNewLn[0] == '{') && (pTestBrace -> attrib == 1)) )
  1907.          {
  1908.             delete pTestBrace;
  1909.          }
  1910.          else if ( (pBraceOnCurLn != NULL) &&
  1911.                    ((pBraceOnCurLn[strlen(pBraceOnCurLn)-1] == '{') && (pTestBrace -> attrib == 1)) )
  1912.               {
  1913.                    delete pTestBrace;
  1914.               }
  1915.               else
  1916.                    pIMode -> push (pTestBrace);
  1917.  
  1918.  
  1919.        /*******************************
  1920.             if (pBraceOnNewLn != NULL)
  1921.             {
  1922.                if ((pBraceOnNewLn[0] == '{') && (pTestBrace -> attrib == 1))
  1923.                    delete pTestBrace;
  1924.                else if (pBraceOnCurLn != NULL)
  1925.                     {
  1926.                        if ((pBraceOnCurLn[strlen(pBraceOnCurLn)-1] == '{') && (pTestBrace -> attrib == 1))
  1927.                            delete pTestBrace;
  1928.                        else
  1929.                            pIMode -> push (pTestBrace);
  1930.                     }
  1931.                     else
  1932.                         pIMode -> push (pTestBrace);
  1933.  
  1934.             }
  1935.             else if (pBraceOnCurLn != NULL)
  1936.                  {
  1937.                     if ((pBraceOnCurLn[strlen(pBraceOnCurLn)-1] == '{') && (pTestBrace -> attrib == 1))
  1938.                         delete pTestBrace;
  1939.                     else
  1940.                         pIMode -> push (pTestBrace);
  1941.                  }
  1942.                  else
  1943.                      pIMode -> push (pTestBrace);
  1944.            **************** */
  1945.     }
  1946.  
  1947.     //#### Indent code if code available, in a case statement
  1948.     if (pIMode -> status () > 0)
  1949.         pLines = IndentNonBraceCode (pLines, pIMode, userS);
  1950.  
  1951.     if (pLines -> status () < minLimit)
  1952.                return pLines;
  1953.  
  1954.     // determine if current line has a single line keyword ! (if, else, while, for, do)
  1955.     if ( ((OutputStruct*) pLines -> peek (1)) -> pCode     != NULL)
  1956.     {
  1957.         // test the exisitance of a key word !
  1958.         int     findWord = 0;
  1959.         char*   pTestCode = ((OutputStruct*) pLines -> peek (1)) -> pCode;
  1960.         while (findWord < IndentWordLen)
  1961.         {
  1962.               char* pTest = strstr (pTestCode, pIndentWords[findWord]);
  1963.               if (pTest == pTestCode) // word found, and at start location of string, else some funny code !
  1964.                     break;
  1965.  
  1966.               findWord++;
  1967.         }
  1968.  
  1969.         // if keyword found, check if next line not a brace or, comment !
  1970.         pTestCode = ((OutputStruct*) pLines -> peek (1)) -> pCode;
  1971.  
  1972.         // Test if code not NULL, and No Hidden Open Braces
  1973.         if ( (pTestCode != NULL) && 
  1974.               (((pTestCode [strlen (pTestCode) - 1] == '{')   ||
  1975.                 (pTestCode [strlen (pTestCode) - 1] == ';'))  ||
  1976.                 (pTestCode [strlen (pTestCode) - 1] == '}')) )
  1977.                            pTestCode = NULL;
  1978.  
  1979.         // Test if open brace not located on next line
  1980.         if ((pTestCode != NULL) && (findWord < IndentWordLen))
  1981.         {
  1982.                 pTestCode = ((OutputStruct*) pLines -> peek (minLimit)) -> pBrace;
  1983.  
  1984.                 if ((pTestCode != NULL) && (pTestCode[0] == '{'))
  1985.                     pTestCode = NULL;    // Dont process line as a single indentation !
  1986.                 else
  1987.                     pTestCode = "E";     // make sure pointer is not null !
  1988.         }
  1989.  
  1990.         if ((findWord < IndentWordLen) && (pTestCode != NULL))
  1991.         // create new structure !
  1992.         {
  1993.             IndentStruct* pIndent = new IndentStruct();
  1994.  
  1995.             // #### memory allocation error
  1996.             if (pIndent == NULL)
  1997.             {
  1998.                 delete pLines;
  1999.                 delete pIMode;
  2000.                 return NULL;
  2001.             }
  2002.  
  2003.             // do indent mode for (if, while, for, else)
  2004.             if ((findWord >= 0) && (findWord < MultiIndent))
  2005.             {
  2006.                 pTestCode = ((OutputStruct*) pLines -> peek (1)) -> pCode;
  2007.  
  2008.                 pIndent -> attrib = 1; // single indent !
  2009.                 
  2010.                 // determine how much to indent the next line of code !
  2011.                 pIndent -> singleIndentLen = strlen (pIndentWords[findWord]);
  2012.  
  2013.                 // test if these is a space after statement.
  2014.                 pTestCode += pIndent -> singleIndentLen;
  2015.                 while (*pTestCode == ' ')
  2016.                 {
  2017.                     pTestCode++;
  2018.                     pIndent -> singleIndentLen++;
  2019.                 }                                
  2020.             }
  2021.             else // it's a case statement !
  2022.             {
  2023.                 pIndent -> attrib = 2; // multiple indent !
  2024.                 pIndent -> pos    = (((OutputStruct*) pLines -> peek (1)) -> indentSpace) - userS.tabSpaceSize;
  2025.             }
  2026.  
  2027.             // place item on stack !
  2028.             pIMode -> push (pIndent);
  2029.         }
  2030.         else
  2031.         {
  2032.             // update pIMode indent queue, throw out single indents if
  2033.             // not needed (i.e multi line single if conditions)
  2034.             IndentStruct* pThrowOut = NULL;
  2035.  
  2036.             // Test code for single indentation, if semi-colon exits
  2037.             // within code, remove item from indent stack!
  2038.             pTestCode = ((OutputStruct*) pLines -> peek (1)) -> pCode ;
  2039.  
  2040.             for (;;)
  2041.             {
  2042.                 if (pIMode -> status () > 0)
  2043.                     pThrowOut = (IndentStruct*) pIMode -> pop();
  2044.                 else
  2045.                     break;            // leave loop
  2046.  
  2047.                 if (pThrowOut -> attrib >= 2)
  2048.                 {
  2049.                     pIMode -> push (pThrowOut);
  2050.                     break;
  2051.                 }    // Test single code indents for a semicolon !
  2052.                 else if (pTestCode [strlen(pTestCode)-1] == ';')
  2053.                          delete pThrowOut; // throw out the single indent item
  2054.                      else
  2055.                      {
  2056.                          pIMode -> push (pThrowOut); // Place item back on stack!
  2057.                          break; // Leave loop!
  2058.                      }
  2059.  
  2060.             }
  2061.         }
  2062.  
  2063.     }
  2064.     return pLines;
  2065. }
  2066.  
  2067.  
  2068. // ----------------------------------------------------------------------------
  2069. // Function reformats open braces to be on the same lines as the
  2070. // code that it's assigned (if possible).
  2071. //
  2072. // Parameters:
  2073. // pLines     : Pointer to a OutputStructure queue object
  2074. // userS      : Users configuration settings.
  2075. //
  2076. // Return Values:
  2077. // QueueList* : Returns a pointer to a newly constructed OutputStructure
  2078. //              queue.
  2079. //
  2080. QueueList* ReformatBraces (QueueList* pLines, Config userS)
  2081. {
  2082.     QueueList*    pNewLines     = new QueueList();
  2083.  
  2084.     int           queueNum      = pLines -> status (); // get queue number
  2085.     int           findBrace;    // position in queue where first brace line is located
  2086.     int           findCode ;    // position in queue where next code line is located
  2087.  
  2088.     OutputStruct* pBraceLine    = NULL;
  2089.     OutputStruct* pCodeLine     = NULL;
  2090.  
  2091.     if (pNewLines == NULL)
  2092.     {
  2093.         delete pLines;
  2094.         return NULL;     // out of memory
  2095.     }
  2096.  
  2097.     // Cant process less than two items (i.e. move brace from one line to next line to make one line )
  2098.     if (queueNum  < 2)
  2099.     {
  2100.         delete pNewLines; // free object that wasn't used !
  2101.         return pLines;
  2102.     }
  2103.  
  2104.     // search forward through queue to find the first appearance of a brace !
  2105.     findBrace = 1;
  2106.     while (findBrace <= queueNum)
  2107.     {
  2108.         pBraceLine = (OutputStruct*) pLines -> peek (findBrace);
  2109.  
  2110.         if ((pBraceLine -> pBrace != NULL) && (pBraceLine -> pBrace[0] == '{'))
  2111.             break;                 // leave queue search !
  2112.         else
  2113.             findBrace++;
  2114.     }
  2115.  
  2116.     if (findBrace > queueNum)      // open brace not found in queue !
  2117.     {
  2118.         delete pNewLines;
  2119.         return pLines;
  2120.     }
  2121.  
  2122.     // find out td; // get queue number
  2123.     int           finy        case (2):
  2124.   ut td; // gin switchs'.
  2125. //
  2126. // Parameters:
  2127. ruct*;
  2128.    tike items are stored // gin swit      }
  2129.             else
  2130.                     return NULL; // memort----pBraoier writtingc;   //##
  2131.                 charturn NULL; spaces & tabs
  2132.         {
  2133.             int numOfSpcs = 0;
  2134.  
  2135.         comment
  2136.